package com.browsesoft.dbtools;

import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.browsesoft.EntityManager;
import com.browsesoft.PropertiesService;

/**
 * 根据属性文件进行加载和转换
 */
public class ObjectManager {
	/**
	 * 从属性文件中负责加载数据源
	 */
	public void loadSource(Map map) throws Exception {
		Document doc = (Document) PropertiesService.getDocument();
		// 对于每一个要转换的类
		NodeList elements = doc.getElementsByTagName("class");
		// 对于每一个子元素
		for (int i = 0; i < elements.getLength(); i++) {
			Element element = (Element) elements.item(i);
			// 取类名
			String className = element.getAttribute("classname");
			// 取表名
			String tableName = element.getAttribute("tablename");
			// 取实体类型
			String entityType = element.getAttribute("entitytype");
			// 数据源
			Element env = (Element) element.getElementsByTagName("source")
					.item(0);
			String sourceName = env.getAttribute("name");
			ObjectSource objectSource = (ObjectSource) Class
					.forName(sourceName).newInstance();
			// 设置数据源环境
			objectSource.setEnvironment(env);
			// 得到字段的对应关系
			Collection maps = this.getAttributeMap(element);
			// 取数据源表名
			String sourceTableName = env.getAttribute("tablename");
			// 取条件
			String condition = env.getAttribute("condition");
			// 清除所有事后处理对象
			EntityManager.getInstance().clearComplete();
			// 让数据源转换
			this.loadConvertData(objectSource, className, sourceTableName,
					condition, maps, tableName, entityType);
			// 让所有事后处理对象执行事后处理方法
			this.dealCompletes();
		}
	}

	/**
	 * 让所有事后处理对象执行事后处理方法
	 */
	public void dealCompletes() {
		// 对于每一个事后处理对象
		Iterator iter = EntityManager.getInstance().getCompletes();
		while (iter.hasNext()) {
			Complete entity = (Complete) iter.next();
			// 执行事后处理
			entity.doComplete();
		}
	}

	/**
	 * 得到字段的对应关系
	 * 
	 * @param e
	 *            属性文件中的描述元素
	 * @return 字段的对应关系列表
	 */
	private Collection getAttributeMap(Element e) {
		Collection result = new LinkedList();
		// 对于每一个对应关系
		NodeList nl = e.getElementsByTagName("attribute");
		for (int i = 0; i < nl.getLength(); i++) {
			Element attr = (Element) nl.item(i);
			// 根据新旧属性名，构造对应关系，放到结果中
			String oldAttribute = attr.getAttribute("source");
			String newAttribute = attr.getAttribute("target");
			result.add(new AttributeMap(oldAttribute, newAttribute));
		}
		return result;
	}

	/**
	 * 从对象源要数据，加载数据,处理对象，并且实例化成对象，让对象自己存储
	 */
	public void loadConvertData(ObjectSource objectSource, String className,
			String sourceTableName, String condition, Collection maps,
			String tableName, String entityType) {
		System.out.println("table is:" + tableName);
		Iterator source = objectSource.getData(sourceTableName, condition);
		long time = System.currentTimeMillis();
		int count = 0;
		// 对于每一条数据
		while (source.hasNext()) {
			try {
				count++;
				if (count % 50 == 0) {
					System.out.println(count + ":"
							+ (System.currentTimeMillis() - time));
					time = System.currentTimeMillis();
				}
				Map attrs = (Map) source.next();
				// 根据对应关系对数据进行转换
				attrs = new Hashtable(this.getAttributes(maps, attrs));
				// 设置对象的实体类型
				attrs.put("entitytype", entityType);
				// 设置对象的数据库表
				attrs.put("tablename", tableName);
				// 构造一个对象
				DataConvert entity = (DataConvert) EntityManager.newObject(
						className, attrs);
				// 对象自己进行数据处理
				entity.convert(count - 1);
			} catch (Exception ex) {
				ex.printStackTrace();
				System.out.println(" error occured when processed " + count);
			}
		}
		System.out.println("count:" + count);
	}

	/**
	 * 根据对应关系对属性进行转换
	 * 
	 * @param maps
	 *            对应关系
	 * @param attrs
	 *            属性
	 */
	private Map getAttributes(Collection maps, Map attrs) {
		// 对于对应关系中的每一项
		Iterator iter = maps.iterator();
		while (iter.hasNext()) {
			AttributeMap item = (AttributeMap) iter.next();
			// 利用新属性名替换旧属性名
			String value = (String) attrs.get(item.oldAttribute);
			if (value == null) {
				throw new RuntimeException("属性名错误：" + item.oldAttribute);
			}
			attrs.remove(item.oldAttribute);
			// 如果有新属性
			String newAttributes = item.newAttribute;
			if (newAttributes != null && !newAttributes.equals("")) {
				// 替换
				attrs.put(newAttributes, value);
			}
		}
		return attrs;
	}

	/**
	 * 属性的对应关系
	 */
	private class AttributeMap {
		// 旧属性
		private String oldAttribute;

		// 新属性
		private String newAttribute;

		/**
		 * 使用新旧属性构造
		 */
		private AttributeMap(String oldAttribute, String newAttribute) {
			this.oldAttribute = oldAttribute;
			this.newAttribute = newAttribute;
		}
	}
}